#include "stdafx.h"

#include "Security.h"


Security::Security(void)
{

return;

}


SecByteBlock Security::generaSHAkey(SecByteBlock mysecretkey){

// Calculate a SHA-256 hash over the Diffie-Hellman session key
SecByteBlock key(SHA256::DIGESTSIZE);
SHA256().CalculateDigest(key,mysecretkey,mysecretkey.size()); 
return key;
}

SecByteBlock Security::generaHMACkey(SecByteBlock mySHAkey, int secretkeylength,string label){

byte hmacOutputBuffer[ CryptoPP::SHA256::DIGESTSIZE ];
memset( hmacOutputBuffer, 0x00, CryptoPP::SHA256::DIGESTSIZE );
SecByteBlock keyhmac;
 

 char* charData;
 charData =const_cast<char*>(label.c_str());
 
//trasformo la stringa in ingresso in un array di byte
byte *byteData=(byte*)charData;
 
   
 // Run the HMAC calculation

 	//calcolo sha del plaintext
	SecByteBlock shaplain(CryptoPP::SHA256::DIGESTSIZE);
	SHA256().CalculateDigest(shaplain, byteData, label.size());
	CryptoPP::HMAC<SHA256 >(mySHAkey,secretkeylength).CalculateDigest( hmacOutputBuffer,shaplain,CryptoPP::SHA256::DIGESTSIZE);
 
 
/*Nel caso in cui passo il testo in chiaro
CryptoPP::HMAC<SHA256 >(mySHAkey,secretkeylength).CalculateDigest( hmacOutputBuffer,byteData,label.size() );
*/

//valorizzo keyhmac , riempendola con l'array di byte ricavato
keyhmac.Assign(hmacOutputBuffer,CryptoPP::SHA256::DIGESTSIZE);

	
return keyhmac;
}


void Security::dhSender(){
CryptoPP::Integer iGenerator(DH_GENERATOR);
CryptoPP::Integer iPrime(DH_PRIME);

//instanzo un seme e calcolo un numero casuale
AutoSeededRandomPool arngA;
RandomNumberGenerator& rngA = *dynamic_cast<RandomNumberGenerator *>(&arngA); 

DH dhA(iPrime,iGenerator);
SecByteBlock privA(dhA.PrivateKeyLength());
SecByteBlock pubA(dhA.PublicKeyLength());
SecByteBlock secretKeyA(dhA.AgreedValueLength());
dhA.GenerateKeyPair(rngA, privA, pubA);
//calcolo della chiave pubblica, privata 

this->pub=pubA;
this->priv=privA;
this->secretkey=secretKeyA;
this->dh=dhA;
this->iPrime=iPrime;
this->iGenerator=iGenerator;

return;

}


string Security::convertkeytostring(SecByteBlock key,int keysize){


//converte una chiave in stringa, usando un eggetto Encoder , valorizza StringSink
CryptoPP::HexEncoder encoder( NULL, true, 0);
string sink;
encoder.Attach( new CryptoPP::StringSink( sink ) );
    
encoder.Put( key,keysize);
encoder.MessageEnd();
 
return sink;

}	

string Security::convertkeytoshortstring(SecByteBlock key,int keysize){


CryptoPP::HexEncoder encoder( NULL, true, 0);
string sink;
encoder.Attach( new CryptoPP::StringSink( sink ) );
    
encoder.Put( key,keysize);
encoder.MessageEnd();
    //converto la chiave in stringa, successivamente in array di byte
 char *c=const_cast<char*>(sink.c_str());
 
 uint8_t lookuptable[8];
 char result[8];

 memset( result, 0x00, 8);
 
//prendo 8 valori casuali
lookuptable[0]=(uint8_t)c[15];
lookuptable[1]=(uint8_t)c[28];
lookuptable[2]=(uint8_t)c[30];
lookuptable[3]=(uint8_t)c[12];
lookuptable[4]=(uint8_t)c[9];
lookuptable[5]=(uint8_t)c[7];
lookuptable[6]=(uint8_t)c[21];
lookuptable[7]=(uint8_t)c[23];

//applico una lookuptable
result[0]=this->lookuptable(lookuptable[0]);
result[1]=this->lookuptable(lookuptable[1]);
result[2]=this->lookuptable(lookuptable[2]);
result[3]=this->lookuptable(lookuptable[3]);
result[4]=this->lookuptable(lookuptable[4]);
result[5]=this->lookuptable(lookuptable[5]);
result[6]=this->lookuptable(lookuptable[6]);
result[7]=this->lookuptable(lookuptable[7]);

//valorizzo la stringa vocale

string ret;
ret.assign(result,8);
return ret;



}



char Security::lookuptable(uint8_t val){

	   char table[20]={'A', 'C', 'G', 'P', 'T',
										 'L', 'E','I', 'V', 'M',
										 'D', 'S', 'O', 'B', 'Z',
										 '2', '3', '6', '7', '9' };

		char out;
		int index;

	   index= val%20;
	   out=table[index];


	   return out;


}
	

char* Security::calculatecounter(SecByteBlock mykey, int lengthkey,uint16_t number){

//metto nei primi due byte il counter , nei restanti 30 la chiave troncata a 30 byte .
	char buffer[33];
	char *ret;
	ret=(char*)malloc(33*sizeof(char));
	char tmp[2];
	uint16_t mynumber=0;
	
	mynumber=number;
	memset (&tmp,0x00, 2);
	memcpy(tmp,&mynumber,sizeof(number));
	
	byte * elem=mykey.BytePtr();
	
	memset (buffer,0x00, 33);
	memset (ret,0x00, 33);
	
	
	memcpy(buffer,tmp,sizeof(tmp));
	memcpy(buffer+2,elem,30);
	buffer[32]='\0';
	

	memcpy(ret,buffer,33);	
	return ret;
	
	

}


CryptoPP::CTR_Mode< CryptoPP::AES >::Encryption Security::calculatekeystream(char *mycounter,SecByteBlock key){


CryptoPP::CTR_Mode< CryptoPP::AES >::Encryption Encryptor;
  
byte *byteData=(byte*)mycounter;
//byte * elem=key.BytePtr();

//Encryptor.SetKeyWithIV( elem, 32, byteData);		//unisce il counter alla chiave
Encryptor.SetKeyWithIV( key, 32, byteData);
return Encryptor;
}


CryptoPP::CTR_Mode< CryptoPP::AES >::Decryption Security::decryptkeystream(char *mycounter,SecByteBlock key){

 CryptoPP::CTR_Mode< CryptoPP::AES >::Decryption Decryptor;
  
byte *byteData=(byte*)mycounter;
//byte * elem=key.BytePtr();
Decryptor.SetKeyWithIV( key, 32, byteData);		//unisce il counter alla chiave

return Decryptor;
}


string Security::plaintextxorblockchiper(string plaintext,CTR_Mode< CryptoPP::AES >::Encryption myEncryptor){

	string ChiperText;
	
	//XOR tra Block chiper e PlainText
    CryptoPP::StringSource( plaintext, true,
        new CryptoPP::StreamTransformationFilter(
          myEncryptor,
          new CryptoPP::StringSink( ChiperText )
        ) // StreamTransformationFilter
    ); // StringSource
	
	
	return ChiperText;
}

string Security::chipertextxorblockchiper(string chipertext,CTR_Mode< CryptoPP::AES >::Decryption myDecryptor){

	string RecoveredText;

		//XOR tra Block chiper e PlainText
    CryptoPP::StringSource( chipertext, true,
        new CryptoPP::StreamTransformationFilter(
          myDecryptor,
          new CryptoPP::StringSink( RecoveredText )
        ) // StreamTransformationFilter
    ); // StringSource
	
	
	return RecoveredText;
}


void Security::dhReceiver(Integer myiPrime, Integer myiGenerator){

AutoSeededRandomPool arngB;
RandomNumberGenerator& rngB = *dynamic_cast<RandomNumberGenerator *>(&arngB); 

// Initialize the Diffie-Hellman class with the prime and base that Alice generated.
DH dhB(iPrime, iGenerator);

SecByteBlock privB(dhB.PrivateKeyLength());
SecByteBlock pubB(dhB.PublicKeyLength());
SecByteBlock secretKeyB(dhB.AgreedValueLength());

dh.GenerateKeyPair(rngB, privB, pubB);


this->iPrime=myiPrime;
this->iGenerator=myiGenerator;
this->dh=dhB;
this->pub=pubB;
this->priv=privB;
this->secretkey=secretKeyB;

return;
}

bool Security::calcolasecretkey(SecByteBlock pub){

if (!this->dh.Agree(this->secretkey, this->priv,pub))
	return false;

	return true;

}



Integer Security::getiPrime(){
	
	return this->iPrime;
}


Integer Security::getiGenerator(){
	
	return this->iGenerator;
}

SecByteBlock Security::getpub(){
	
	return this->pub;
}

SecByteBlock Security::getpubEP(){
	
	return this->pubEP;
}

SecByteBlock Security::getpriv(){
	
	return this->priv;
}

SecByteBlock Security::getsecretkey(){
	
	return this->secretkey;
}

SecByteBlock Security::getSHAkey(){
	
	return this->SHAkey;
}

void Security::setSHAkey(SecByteBlock mySHAkey){

	this->SHAkey=mySHAkey;
	
	return;
}

SecByteBlock Security::getHMACvect_TX(){
	
	return this->HMACvect_TX;
}

void Security::setHMACvect_TX(SecByteBlock myHMACvect){

	this->HMACvect_TX=myHMACvect;
	
	return;
}

SecByteBlock Security::getHMACvect_RX(){
	
	return this->HMACvect_RX;
}

void Security::setHMACvect_RX(SecByteBlock myHMACvect){

	this->HMACvect_RX=myHMACvect;
	
	return;
}

string Security::getvoicekey(){
	
	return this->voicekey;
}

void Security::setvoicekey(string myvoicekey){

	this->voicekey=myvoicekey;
	
	return;
}

string Security::getplaintext(){
	
	return this->plaintext;
}

void Security::setplaintext(string myplaintext ){

	this->plaintext=myplaintext;
	
	return;
}

string Security::getchipertext(){
	
	return this->chipertext;
}

void Security::setchipertext(string mychipertext ){

	this->chipertext=mychipertext;
	
	return;
}

string Security::getrecoveredtext(){
	
	return this->recoveredtext;
}

void Security::setrecoveredtext(string myrecoveredtext ){

	this->recoveredtext=myrecoveredtext;
	
	return;
}

char* Security::getcounter(){
	
	return this->counter;
}

void Security::setcounter(char* mycounter ){

	memcpy(this->counter,mycounter,strlen(mycounter));
	return;
}


CryptoPP::CTR_Mode< CryptoPP::AES >::Encryption Security::getEncryptor(){

return this->Encryptor;

}

void Security::setEncryptor(CryptoPP::CTR_Mode< CryptoPP::AES >::Encryption myEncryptor ){

	this->Encryptor=myEncryptor;
	
	return;
}

CryptoPP::CTR_Mode< CryptoPP::AES >::Decryption Security::getDecryptor(){

return this->Decryptor;

}

void Security::setDecryptor(CryptoPP::CTR_Mode< CryptoPP::AES >::Decryption myDecryptor ){

	this->Decryptor=myDecryptor;
	
	return;
}

SecByteBlock Security::getHMACstream_TX(){
	
	return this->HMACstream_TX;
}

void Security::setHMACstream_TX(SecByteBlock myHMACstream){

	this->HMACstream_TX=myHMACstream;
	
	return;
}

SecByteBlock Security::getHMACstream_RX(){
	
	return this->HMACstream_RX;
}

void Security::setHMACstream_RX(SecByteBlock myHMACstream){

	this->HMACstream_RX=myHMACstream;
	
	return;
}

SecByteBlock Security::getHMACconv(){
	
	return this->HMACconv;
}

void Security::setHMACconv(SecByteBlock myHMACconv){

	this->HMACconv=myHMACconv;
	
	return;
}

DH Security::getdh(){
	
	return this->dh;
}

void Security::setpubEP(SecByteBlock mypubEP){
	
	this->pubEP=mypubEP;
	
	return ;
}

